/**
 * 
 */
package com.ginger.rabbitmq.config;

import java.util.UUID;

import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.ConsumerTagStrategy;
import org.springframework.amqp.support.converter.ContentTypeDelegatingMessageConverter;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.ginger.rabbitmq.adapter.MessageDelegate;
import com.ginger.rabbitmq.convert.ImageMessageConverter;
import com.ginger.rabbitmq.convert.PDFMessageConverter;
import com.ginger.rabbitmq.convert.TextMessageConvert;
import com.ginger.rabbitmq.properties.RabbitMQProperties;

/**
 * @Description: RabbitMQ配置类
 * @author 姜锋
 * @date 2019年3月31日 上午8:28:22
 * @version V1.0
 */
@Configuration
@ComponentScan("com.ginger.rabbitmq.*")
public class RabbitConfig {
	// 连接工厂
	@Bean
	public ConnectionFactory connectionFactory() {
		CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
		cachingConnectionFactory
				.setAddresses(RabbitMQProperties.RABBITMQ_HOST + ":" + RabbitMQProperties.RABBITMQ_PORT);
		cachingConnectionFactory.setUsername(RabbitMQProperties.USER_NAME);
		cachingConnectionFactory.setPassword(RabbitMQProperties.PASSWORD);
		cachingConnectionFactory.setVirtualHost(RabbitMQProperties.RABBITMQ_VIRTUAL_HOST);
		return cachingConnectionFactory;
	}
	// Rabbit Admin
	@Bean
	public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
		RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
		rabbitAdmin.setAutoStartup(true);
		return rabbitAdmin;
	}
	// RabbitMQ RabbitTemplate
	@Bean
	public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
		RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
		return rabbitTemplate;
	}
	// 申明一个交换机
	@Bean
	public TopicExchange topic001() {
		return new TopicExchange("topic001", true, false);
	}
	// 申明一个队列
	@Bean
	public Queue queue001() {
		return new Queue("queue001", true);
	}
	// 申明绑定
	@Bean
	public Binding bingding001() {
		return BindingBuilder.bind(queue001()).to(topic001()).with("message.#");
	}
	// 申明死信交换机
	// 申明一个交换机
	@Bean
	public TopicExchange DlxExchange() {
		return new TopicExchange("dlx.exchange", true, false);
	}
	// 申明死信队列
	@Bean
	public Queue DlxQueue() {
		return new Queue("dlx.queue", true);
	}
	// 死信绑定
	@Bean
	public Binding Dlxbingding() {
		return BindingBuilder.bind(DlxQueue()).to(DlxExchange()).with("#");
	}
	
	@Bean
	// 简单消息监听容器
	public SimpleMessageListenerContainer simpleMessageListenerContainer(ConnectionFactory connectionFactory) {
		SimpleMessageListenerContainer simpleMessageListenerContainer = new SimpleMessageListenerContainer(
				connectionFactory);
		//监听多个队列
		simpleMessageListenerContainer.setQueues(queue001(),DlxQueue());
		//当前消费者数量
		simpleMessageListenerContainer.setConcurrentConsumers(1);
		//最大消费者数量
		simpleMessageListenerContainer.setMaxConcurrentConsumers(500);
		//是否允许重回队列
		simpleMessageListenerContainer.setDefaultRequeueRejected(false);
		//签收模式
		simpleMessageListenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
		
		simpleMessageListenerContainer.setExposeListenerChannel(true);
		//消费端标签生成策略
		simpleMessageListenerContainer.setConsumerTagStrategy(new ConsumerTagStrategy() {
			@Override
			public String createConsumerTag(String queue) {
				return queue+"_"+UUID.randomUUID().toString();
			}
		});
		
		/** 1.适配器方式,默认有自己的方法名称,handleMessage,
		 * 也可以指定一个方法名称,consumeMessage
		 * 也可以添加转换器 从字节数组转化为String
		MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(new MessageDelegate());
		messageListenerAdapter.setDefaultListenerMethod("consumeMessage");
		 添加转换器
		messageListenerAdapter.setMessageConverter(new TextMessageConvert());
		 * 注意转换规则
		 * 
		 * */
		
		/**
		 *  2. 适配器方式: 我们的队列名称和方法名称进行一一匹配
		 
		MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(new MessageDelegate());
		Map<String, String> queueOrTagToMethodName = new HashMap<>();
		messageListenerAdapter.setDefaultListenerMethod("consumeMessage");
		queueOrTagToMethodName.put("queue001", "queue001");
		queueOrTagToMethodName.put("queue001", "queue001");
		queueOrTagToMethodName.put("dlx.queue", "dlxMessage");
		messageListenerAdapter.setQueueOrTagToMethodName(queueOrTagToMethodName);
		simpleMessageListenerContainer.setMessageListener(messageListenerAdapter);
		*/
		
		
		/**
		//1.1 Json格式转换器
		MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(new MessageDelegate());
		messageListenerAdapter.setDefaultListenerMethod("consumeMessage");
		Jackson2JsonMessageConverter jackson2JsonMessageConverter  = new Jackson2JsonMessageConverter();
		messageListenerAdapter.setMessageConverter(jackson2JsonMessageConverter);
		simpleMessageListenerContainer.setMessageListener(messageListenerAdapter);
		*/
		
		
		/**
		//1.2 DefaultJackson2JavaTypeMapper & Jackson2JsonMessageConverter 支持Java对象转换
		MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(new MessageDelegate());
		messageListenerAdapter.setDefaultListenerMethod("consumeMessage");
		Jackson2JsonMessageConverter jackson2JsonMessageConverter  = new Jackson2JsonMessageConverter();
		DefaultJackson2JavaTypeMapper defaultJackson2JavaTypeMapper = new DefaultJackson2JavaTypeMapper();
		//增加许可路径
		defaultJackson2JavaTypeMapper.setTrustedPackages("*");
		jackson2JsonMessageConverter.setJavaTypeMapper(defaultJackson2JavaTypeMapper);
		messageListenerAdapter.setMessageConverter(jackson2JsonMessageConverter);
		simpleMessageListenerContainer.setMessageListener(messageListenerAdapter);
		*/
		
		/**
		//1.3 DefaultJackson2JavaTypeMapper & Jackson2JsonMessageConverter 支持Java对象多映射转换
		MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(new MessageDelegate());
		messageListenerAdapter.setDefaultListenerMethod("consumeMessage");
		Jackson2JsonMessageConverter jackson2JsonMessageConverter  = new Jackson2JsonMessageConverter();
		DefaultJackson2JavaTypeMapper defaultJackson2JavaTypeMapper = new DefaultJackson2JavaTypeMapper();
		Map<String, Class<?>> idClassMapping = new HashMap<>();
		idClassMapping.put("order",Order.class);
		idClassMapping.put("packaged",Packaged.class);
		defaultJackson2JavaTypeMapper.setIdClassMapping(idClassMapping);
		jackson2JsonMessageConverter.setJavaTypeMapper(defaultJackson2JavaTypeMapper);
		messageListenerAdapter.setMessageConverter(jackson2JsonMessageConverter);
		simpleMessageListenerContainer.setMessageListener(messageListenerAdapter);
		 */
		
		
		/**
		 * 1.4 ext convert
		 */
		MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(new MessageDelegate());
		messageListenerAdapter.setDefaultListenerMethod("consumeMessage");
		//全局转化器
		ContentTypeDelegatingMessageConverter contentTypeDelegatingMessageConverter = new ContentTypeDelegatingMessageConverter();
		TextMessageConvert textMessageConvert = new TextMessageConvert();
		contentTypeDelegatingMessageConverter.addDelegate("text", textMessageConvert);
		contentTypeDelegatingMessageConverter.addDelegate("html/text", textMessageConvert);
		contentTypeDelegatingMessageConverter.addDelegate("xml/text", textMessageConvert);
		contentTypeDelegatingMessageConverter.addDelegate("text/plain", textMessageConvert);
		
		Jackson2JsonMessageConverter jackson2JsonMessageConverter  = new Jackson2JsonMessageConverter();
		contentTypeDelegatingMessageConverter.addDelegate("json", jackson2JsonMessageConverter);
		contentTypeDelegatingMessageConverter.addDelegate("application/json", jackson2JsonMessageConverter);
		
		ImageMessageConverter imageMessageConverter = new ImageMessageConverter();
		contentTypeDelegatingMessageConverter.addDelegate("image/png", imageMessageConverter);
		contentTypeDelegatingMessageConverter.addDelegate("image", imageMessageConverter);
		
		PDFMessageConverter pdfMessageConverter = new PDFMessageConverter();
		contentTypeDelegatingMessageConverter.addDelegate("application/pdf", pdfMessageConverter);
		messageListenerAdapter.setMessageConverter(contentTypeDelegatingMessageConverter);
		simpleMessageListenerContainer.setMessageListener(messageListenerAdapter);
		return simpleMessageListenerContainer;
		
		
	}
}
